<?php

// ------------------------------------------------------------------------
// |@Author       : Jarmin <edshop@qq.com>
// |@----------------------------------------------------------------------
// |@Date         : 2025-04-05 21:25:32
// |@----------------------------------------------------------------------
// |@LastEditTime : 2025-04-29 07:42:53
// |@----------------------------------------------------------------------
// |@LastEditors  : Jarmin <jarmin@ladmin.cn>
// |@----------------------------------------------------------------------
// |@Description  : 基础模型类 - 扩展ThinkPHP模型功能
// |@----------------------------------------------------------------------
// |@FilePath     : Model.php
// |@----------------------------------------------------------------------
// |@Copyright (c) 2025 http://www.ladmin.cn   All rights reserved.
// ------------------------------------------------------------------------
declare (strict_types=1);

namespace think\admin;

use think\db\exception\DbException;
use think\exception\HttpResponseException;

/**
 * 基础模型类
 * 
 * 扩展功能：
 * 1. 自动时间戳记录
 * 2. 数据字段安全验证
 * 3. 数据权限控制
 * 4. 标准分页方法
 */
class Model extends \think\Model
{
    protected $autoWriteTimestamp = true;
    protected $createTime = 'create_at';
    protected $updateTime = 'update_at';
    protected $deleteTime = 'delete_at';
    protected $useSoftDelete = true;

    protected $type = [
        'status'    => 'integer',
        'is_super'  => 'boolean',
        'meta'      => 'json'
    ];

    /**
     * 插入前回调
     * 自动设置创建人ID
     * 
     * @param \think\Model $model 模型实例
     */
    public static function onBeforeInsert($model)
    {
        $model->setAttr('created_by', request()->userId ?? 0);
    }

    /**
     * 更新前回调  
     * 自动设置更新人ID
     *
     * @param \think\Model $model 模型实例
     */
    public static function onBeforeUpdate($model)
    {
        $model->setAttr('updated_by', request()->userId ?? 0);
    }

    /**
     * 标准分页查询
     *
     * @param array $filter 查询条件
     * @param array $options 分页选项
     * @return array 分页结果
     * @throws HttpResponseException 分页失败时抛出
     */
    public static function paginateList(array $filter = [], array $options = [])
    {
        try {
            $query = static::where($filter);
            $query->order($options['order'] ?? 'create_at desc');
            return $query->paginate($options)->toArray();
        } catch (\HttpResponseException $e) {
            throw new HttpResponseException(lang('model.model_pagination_failed'), 500, $e);
        }
    }

    /**
     * 安全更新数据
     * 会先验证字段合法性再保存
     *
     * @param array $data 更新数据
     * @param bool $strict 是否严格模式(严格模式下不允许更新不存在字段)
     * @return bool 是否更新成功
     */
    public function safeUpdate(array $data, bool $strict = true)
    {
        $this->checkAllowFields($data, $strict);
        return $this->save($data);
    }

    /**
     * 检查允许更新的字段
     *
     * @param array $data 待更新数据
     * @param bool $strict 是否严格模式
     * @throws HttpResponseException 存在非法字段时抛出
     */
    protected function checkAllowFields(array $data, bool $strict)
    {
        $diff = array_diff(array_keys($data), $this->getTableFields());
        if ($strict && !empty($diff)) {
            throw new HttpResponseException(lang('model.model_invalid_fields', ['fields' => implode(',', $diff)]));
        }
    }

    /**
     * 数据权限范围
     * 非管理员只能操作自己创建的数据
     *
     * @param \think\db\Query $query 查询对象
     */
    public function scopeDataAuth($query)
    {
        if (!request()->isSuper) {
            $query->where('created_by', request()->userId);
        }
    }
}
